home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / kernel / mach / sun4.md / machAsm.s < prev    next >
Encoding:
Text File  |  1992-12-19  |  38.7 KB  |  1,355 lines

  1. /* machAsm.s --
  2.  *
  3.  *     Contains misc. assembler routines for the sun4.
  4.  *
  5.  * Copyright (C) 1985 Regents of the University of California
  6.  * All rights reserved.
  7.  *
  8.  * rcs = $Header: /cdrom/src/kernel/Cvsroot/kernel/mach/sun4.md/machAsm.s,v 9.15 91/10/18 01:22:56 dlong Exp $ SPRITE (Berkeley)
  9.  */
  10.  
  11. #include "user/proc.h"
  12. #include "machConst.h"
  13. #include "machAsmDefs.h"
  14. .seg    "text"
  15.  
  16. /*
  17.  * ----------------------------------------------------------------------
  18.  *
  19.  * Mach_GetPC --
  20.  *
  21.  *    Jump back to caller, moving the return address that was put into
  22.  *    %RETURN_ADDR_REG as a side effect of the call into the %RETURN_VAL_REG.
  23.  *
  24.  * Results:
  25.  *    Old pc is returned in %RETURN_VAL_REG.
  26.  *
  27.  * Side effects:
  28.  *    None.
  29.  *
  30.  * ----------------------------------------------------------------------
  31.  */
  32. .globl    _Mach_GetPC
  33. _Mach_GetPC:
  34.     retl
  35.     mov    %RETURN_ADDR_REG, %RETURN_VAL_REG
  36.  
  37.  
  38. /*
  39.  * ----------------------------------------------------------------------
  40.  *
  41.  * Mach_GetCallerPC --
  42.  *
  43.  *    Return the PC of the caller of the routine who called us.
  44.  *
  45.  * Results:
  46.  *    Our caller's caller's pc.
  47.  *
  48.  * Side effects:
  49.  *    None.
  50.  *
  51.  * ----------------------------------------------------------------------
  52.  */
  53. .globl    _Mach_GetCallerPC
  54. _Mach_GetCallerPC:
  55.     retl
  56.     mov    %RETURN_ADDR_REG_CHILD, %RETURN_VAL_REG
  57.  
  58.  
  59. /*
  60.  *---------------------------------------------------------------------
  61.  *
  62.  * Mach_TestAndSet --
  63.  *
  64.  *     int Mach_TestAndSet(intPtr)
  65.  *          int *intPtr;
  66.  *
  67.  *     Test and set an operand.
  68.  *
  69.  * Results:
  70.  *     Returns 0 if *intPtr was zero and 1 if *intPtr was non-zero.  Also
  71.  *     in all cases *intPtr is set to a non-zero value.
  72.  *
  73.  * Side effects:
  74.  *     None.
  75.  *
  76.  *---------------------------------------------------------------------
  77.  */
  78. .globl    _Mach_TestAndSet
  79. _Mach_TestAndSet:
  80.     /*
  81.      * We're a leaf routine, so our return value goes in the save register
  82.      * that our operand does.  Move the operand before overwriting.
  83.      * The ISP description of the swap instruction indicates that it is
  84.      * okay to use the same address and destination registers.  This will
  85.      * put the address into the addressed location to set it.  That means
  86.      * we can't use address 0, but we shouldn't be doing that anyway.
  87.      */
  88. #ifdef SWAP_INSTR_WORKS
  89.     swap    [%RETURN_VAL_REG], %RETURN_VAL_REG    /* set addr with addr */
  90. #else
  91.     ldstub    [%RETURN_VAL_REG], %RETURN_VAL_REG    /* value into reg */
  92. #endif /* SWAP_INSTR_WORKS */
  93.     tst    %RETURN_VAL_REG                /* was it set? */
  94.     be,a    ReturnZero                /* if not, return 0 */
  95.     clr    %RETURN_VAL_REG                /* silly, delay slot */
  96.     mov    0x1, %RETURN_VAL_REG            /* yes set, return 1 */
  97. ReturnZero:
  98.     retl
  99.     nop
  100.  
  101.  
  102. /*
  103.  *---------------------------------------------------------------------
  104.  *
  105.  * Mach_GetMachineType -
  106.  *
  107.  *    Returns the type of machine that is stored in the id prom.
  108.  *
  109.  *    int    Mach_GetMachineType()
  110.  *
  111.  * Results:
  112.  *    The type of machine.
  113.  *
  114.  * Side effects:
  115.  *    None.
  116.  *
  117.  *---------------------------------------------------------------------
  118.  */
  119. #ifndef sun4c
  120. .globl    _Mach_GetMachineType
  121. _Mach_GetMachineType:
  122.     set    VMMACH_MACH_TYPE_ADDR, %o0
  123.     lduba    [%o0] VMMACH_CONTROL_SPACE, %o0
  124.     retl
  125.     nop
  126. #endif /* sun4c */
  127.  
  128.  
  129. /*
  130.  *---------------------------------------------------------------------
  131.  *
  132.  * Mach_GetEtherAddress -
  133.  *
  134.  *    Returns the type of machine that is stored in the id prom.
  135.  *
  136.  *    Net_EtherAddress *Mach_GetEtherAddress(ðerAddress)
  137.  *
  138.  * Results:
  139.  *    The argument struct gets the prom's ethernet address and is
  140.  *    returned.
  141.  *
  142.  * Side effects:
  143.  *    None.
  144.  *
  145.  *---------------------------------------------------------------------
  146.  */
  147. #ifndef sun4c
  148. .globl    _Mach_GetEtherAddress
  149. _Mach_GetEtherAddress:
  150.     set    VMMACH_ETHER_ADDR, %OUT_TEMP1
  151.     /* first byte */
  152.     lduba    [%OUT_TEMP1] VMMACH_CONTROL_SPACE, %OUT_TEMP2
  153.     stb    %OUT_TEMP2, [%o0]
  154.     add    %OUT_TEMP1, VMMACH_IDPROM_INC, %OUT_TEMP1
  155.     add    %o0, 1, %o0
  156.  
  157.     /* second byte */
  158.     lduba    [%OUT_TEMP1] VMMACH_CONTROL_SPACE, %OUT_TEMP2
  159.     stb    %OUT_TEMP2, [%o0]
  160.     add    %OUT_TEMP1, VMMACH_IDPROM_INC, %OUT_TEMP1
  161.     add    %o0, 1, %o0
  162.  
  163.     /* third byte */
  164.     lduba    [%OUT_TEMP1] VMMACH_CONTROL_SPACE, %OUT_TEMP2
  165.     stb    %OUT_TEMP2, [%o0]
  166.     add    %OUT_TEMP1, VMMACH_IDPROM_INC, %OUT_TEMP1
  167.     add    %o0, 1, %o0
  168.  
  169.     /* fourth byte */
  170.     lduba    [%OUT_TEMP1] VMMACH_CONTROL_SPACE, %OUT_TEMP2
  171.     stb    %OUT_TEMP2, [%o0]
  172.     add    %OUT_TEMP1, VMMACH_IDPROM_INC, %OUT_TEMP1
  173.     add    %o0, 1, %o0
  174.  
  175.     /* fifth byte */
  176.     lduba    [%OUT_TEMP1] VMMACH_CONTROL_SPACE, %OUT_TEMP2
  177.     stb    %OUT_TEMP2, [%o0]
  178.     add    %OUT_TEMP1, VMMACH_IDPROM_INC, %OUT_TEMP1
  179.     add    %o0, 1, %o0
  180.  
  181.     /* sixth byte */
  182.     lduba    [%OUT_TEMP1] VMMACH_CONTROL_SPACE, %OUT_TEMP2
  183.     stb    %OUT_TEMP2, [%o0]
  184.     sub    %o0, 5, %o0        /* restore pointer parameter */
  185.  
  186.     retl
  187.     nop
  188. #endif /* sun4c */
  189.  
  190. /*
  191.  *---------------------------------------------------------------------
  192.  *
  193.  * Mach_MonTrap -
  194.  *
  195.  *      Trap to the monitor.  This involves dummying up a trap stack for the
  196.  *      monitor, allowing non-maskable interrupts and then jumping to the
  197.  *      monitor trap routine.  When it returns, non-maskable interrupts are
  198.  *      disabled and we return.
  199.  *
  200.  *    void    Mach_MonTrap(address_to_trap_to)
  201.  *
  202.  * Results:
  203.  *      None.
  204.  *
  205.  * Side effects:
  206.  *      None.
  207.  *
  208.  * --------------------------------------------------------------------
  209.  */
  210. .global    _Mach_MonTrap
  211. _Mach_MonTrap:
  212.     save    %sp, -MACH_SAVED_STATE_FRAME, %sp
  213.     /* enable non-maskable interrupts? */
  214.     /* get address */
  215.     call    %i0
  216.     nop
  217.     /* disable non-maskable interrupts? */
  218.     ret
  219.     restore
  220.  
  221.  
  222. /*
  223.  *---------------------------------------------------------------------
  224.  *
  225.  * Mach_ContextSwitch -
  226.  *
  227.  *    Mach_ContextSwitch(fromProcPtr, toProcPtr)
  228.  *
  229.  *    Switch the thread of execution to a new process.  This routine
  230.  *    is passed a pointer to the process to switch from and a pointer to
  231.  *    the process to switch to.  It goes through the following steps:
  232.  *
  233.  *    1) Change to the new context.
  234.  *    2) save stuff
  235.  *    3) restore stuff
  236.  *    4) Return in the new process
  237.  *
  238.  *    The kernel stack is changed implicitly when the registers are restored.
  239.  *
  240.  * Results:
  241.  *    None.
  242.  *
  243.  * Side effects:
  244.  *    The kernel stack, all general registers, and some special-purpose
  245.  *    registers are changed.
  246.  *
  247.  *---------------------------------------------------------------------
  248.  */
  249. .globl    _Mach_ContextSwitch
  250. _Mach_ContextSwitch:
  251.     /*
  252.      * We call stuff here, so we need a new window.  An overflow trap
  253.      * is okay here.  Save enough space for the context switch state on
  254.      * the stack.
  255.      */
  256.     save     %sp, -MACH_SAVED_STATE_FRAME, %sp
  257.     mov    %psr, %CUR_PSR_REG
  258.  
  259.     /*
  260.      * Enable the floating point processor so we can save and
  261.      * restore FPU state if necessary.
  262.      */
  263.     set    MACH_ENABLE_FPP, %VOL_TEMP1
  264.     or    %CUR_PSR_REG,%VOL_TEMP1,%VOL_TEMP1
  265.     mov    %VOL_TEMP1, %psr
  266.     /*
  267.      * No delay instructions needed here as long as the following
  268.      * three instructions don't touch the FPU.
  269.      *
  270.      * Save stack pointer into state struct.  This is also the pointer
  271.      * in the mach state struct of the saved context switch state.  It
  272.      * just so happens it's stored on the stack...
  273.      */
  274.     sethi    %hi(_machStatePtrOffset), %VOL_TEMP1
  275.                             /* get offset */
  276.     ld    [%VOL_TEMP1 + %lo(_machStatePtrOffset)], %VOL_TEMP1
  277.         /* FPU is now active. */
  278.     add    %i0, %VOL_TEMP1 , %VOL_TEMP1        /* add to base */
  279.     ld    [%VOL_TEMP1], %SAFE_TEMP        /* get machStatePtr */
  280.     add    %SAFE_TEMP, MACH_SWITCH_REGS_OFFSET, %VOL_TEMP1
  281.     st    %sp, [%VOL_TEMP1]
  282.  
  283.     /*
  284.      * If FPU is active for this process, save FPU state.
  285.      */
  286.     ld    [%SAFE_TEMP+MACH_FPU_STATUS_OFFSET], %VOL_TEMP1
  287.     tst    %VOL_TEMP1
  288.     bz    noFPUactive
  289.     /*
  290.      *  Note: Part of following set instruction executed in "bz" delay
  291.      *  slot.  This trashes %VOL_TEMP1 when the branch is taken.
  292.      *
  293.      *  We are saving the user's FPU state into the trap regs during
  294.      *  the context switch because we don't want the latency of saving
  295.      *  all the floating point state on every trap.  This works because
  296.      *  the kernel doesn't user floating point instructions.
  297.      *
  298.      *  Tricky code - We save the fromProcPtr in _machFPUSaveProcPtr and
  299.      *  execute a "st %fsr". The "st fsr" will pause until all FPU ops
  300.      *  are compete.  If any FPU execptions are pending we will get a
  301.      *  FP_EXCEPTION trap on the instruction marked by the label
  302.      *  _machFPUSyncInst. The routine MachHandleTrap in
  303.      *  machCode.c will catch this fault and note it in the processes
  304.      *  PCB.
  305.      */
  306.     sethi    %hi(_machFPUSaveProcPtr), %VOL_TEMP1
  307.     st    %i0, [%VOL_TEMP1 + %lo(_machFPUSaveProcPtr)];
  308.     /*
  309.      * Set %SAFE_TEMP to be trapRegsPtr.
  310.      */
  311.     ld    [%SAFE_TEMP + MACH_TRAP_REGS_OFFSET], %SAFE_TEMP
  312. .global _machFPUSyncInst
  313. _machFPUSyncInst: st    %fsr, [%SAFE_TEMP + MACH_FPU_FSR_OFFSET]
  314.         /*
  315.      * The following symbol is include to make the following code
  316.      * be attributed to the routine Mach_ContextSwitch2 and not
  317.      * _machFPUSyncInst.
  318.      */
  319. .globl    Mach_ContextSwitch2
  320. Mach_ContextSwitch2:
  321.     std %f0, [%SAFE_TEMP + MACH_FPU_REGS_OFFSET + 4*0]
  322.     std %f2, [%SAFE_TEMP + MACH_FPU_REGS_OFFSET + 4*2]
  323.     std %f4, [%SAFE_TEMP + MACH_FPU_REGS_OFFSET + 4*4]
  324.     std %f6, [%SAFE_TEMP + MACH_FPU_REGS_OFFSET + 4*6]
  325.     std %f8, [%SAFE_TEMP + MACH_FPU_REGS_OFFSET + 4*8]
  326.     std %f10, [%SAFE_TEMP + MACH_FPU_REGS_OFFSET + 4*10]
  327.     std %f12, [%SAFE_TEMP + MACH_FPU_REGS_OFFSET + 4*12]
  328.     std %f14, [%SAFE_TEMP + MACH_FPU_REGS_OFFSET + 4*14]
  329.     std %f16, [%SAFE_TEMP + MACH_FPU_REGS_OFFSET + 4*16]
  330.     std %f18, [%SAFE_TEMP + MACH_FPU_REGS_OFFSET + 4*18]
  331.     std %f20, [%SAFE_TEMP + MACH_FPU_REGS_OFFSET + 4*20]
  332.     std %f22, [%SAFE_TEMP + MACH_FPU_REGS_OFFSET + 4*22]
  333.     std %f24, [%SAFE_TEMP + MACH_FPU_REGS_OFFSET + 4*24]
  334.     std %f26, [%SAFE_TEMP + MACH_FPU_REGS_OFFSET + 4*26]
  335.     std %f28, [%SAFE_TEMP + MACH_FPU_REGS_OFFSET + 4*28]
  336.     std %f30, [%SAFE_TEMP + MACH_FPU_REGS_OFFSET + 4*30]
  337. noFPUactive:
  338.     /*
  339.      * Save context switch state, globals only for the time being...
  340.      * This gets saved in our stack frame.
  341.      */
  342.     MACH_SAVE_GLOBAL_STATE()
  343.  
  344.     /*
  345.      * Now make sure all windows are flushed to the stack.  We do this
  346.      * with MACH_NUM_WINDOWS - 1 saves and restores.  The window overflow
  347.      * and underflow traps will then handle this for us.  We put the counter
  348.      * in a global, since they have all been saved already and are free
  349.      * for our use and we need the value across windows.
  350.      */
  351.  
  352.     sethi    %hi(_machNumWindows), %g2
  353.     ld    [%g2 + %lo(_machNumWindows)], %g2
  354.     sub    %g2, 1, %g1
  355. ContextSaveSomeMore:
  356.     save
  357.     subcc    %g1, 1, %g1
  358.     bne    ContextSaveSomeMore
  359.     nop
  360.     sub    %g2, 1, %g1
  361. ContextRestoreSomeMore:
  362.     restore
  363.     subcc    %g1, 1, %g1
  364.     bne    ContextRestoreSomeMore
  365.     nop
  366.  
  367.     /*
  368.      * Switch contexts to that of toProcPtr.  It's the second arg, so
  369.      * move it to be first arg of routine we call.
  370.      */
  371.     mov    %i1, %o0
  372.     call    _VmMach_SetupContext, 1
  373.     nop
  374.     /*
  375.      * Context to use was returned in %RETURN_VAL_REG.  Set the context
  376.      * to that value.  VmMachSetContextReg is a leaf routine, so we
  377.      * leave the value for its argument in %RETURN_VAL_REG.
  378.      */
  379.     call    _VmMachSetContextReg, 1
  380.     nop
  381.  
  382.     /*
  383.      * Restore stack pointer of new process - WE SWITCH STACKS HERE!!!
  384.      * the pointer to the new processes' state structure goes into
  385.      * %SAFE_TEMP.
  386.      */
  387.     sethi    %hi(_machStatePtrOffset), %VOL_TEMP1
  388.                         /* get offset */
  389.     ld    [%VOL_TEMP1 + %lo(_machStatePtrOffset)], %VOL_TEMP1
  390.     add    %i1, %VOL_TEMP1, %VOL_TEMP1    /* &(procPtr->machStatePtr) */
  391.     ld    [%VOL_TEMP1], %SAFE_TEMP    /* procPtr->machStatePtr */
  392.     add    %SAFE_TEMP, MACH_SWITCH_REGS_OFFSET, %VOL_TEMP1
  393.     ld    [%VOL_TEMP1], %sp
  394.  
  395.     /* Update machCurStatePtr */
  396.     sethi    %hi(_machCurStatePtr), %VOL_TEMP1
  397.     st    %SAFE_TEMP, [%VOL_TEMP1 + %lo(_machCurStatePtr)]
  398.     /*
  399.      * If FPU is active for this process, restore the FPU state.
  400.      */
  401.     ld    [%SAFE_TEMP+MACH_FPU_STATUS_OFFSET], %VOL_TEMP1
  402.     tst    %VOL_TEMP1
  403.     bz    dontRestoreFPU
  404.     nop
  405.     /*
  406.      * Set %SAFE_TEMP to be machStatePtr.
  407.      */
  408.     ld  [%SAFE_TEMP + MACH_TRAP_REGS_OFFSET], %SAFE_TEMP
  409.     ld  [%SAFE_TEMP + MACH_FPU_FSR_OFFSET], %fsr
  410.     ldd [%SAFE_TEMP + MACH_FPU_REGS_OFFSET + 4*0],%f0
  411.     ldd [%SAFE_TEMP + MACH_FPU_REGS_OFFSET + 4*2],%f2
  412.     ldd [%SAFE_TEMP + MACH_FPU_REGS_OFFSET + 4*4],%f4
  413.     ldd [%SAFE_TEMP + MACH_FPU_REGS_OFFSET + 4*6],%f6
  414.     ldd [%SAFE_TEMP + MACH_FPU_REGS_OFFSET + 4*8],%f8
  415.     ldd [%SAFE_TEMP + MACH_FPU_REGS_OFFSET + 4*10],%f10
  416.     ldd [%SAFE_TEMP + MACH_FPU_REGS_OFFSET + 4*12],%f12
  417.     ldd [%SAFE_TEMP + MACH_FPU_REGS_OFFSET + 4*14],%f14
  418.     ldd [%SAFE_TEMP + MACH_FPU_REGS_OFFSET + 4*16],%f16
  419.     ldd [%SAFE_TEMP + MACH_FPU_REGS_OFFSET + 4*18],%f18
  420.     ldd [%SAFE_TEMP + MACH_FPU_REGS_OFFSET + 4*20],%f20
  421.     ldd [%SAFE_TEMP + MACH_FPU_REGS_OFFSET + 4*22],%f22
  422.     ldd [%SAFE_TEMP + MACH_FPU_REGS_OFFSET + 4*24],%f24
  423.     ldd [%SAFE_TEMP + MACH_FPU_REGS_OFFSET + 4*26],%f26
  424.     ldd [%SAFE_TEMP + MACH_FPU_REGS_OFFSET + 4*28],%f28
  425.     ldd [%SAFE_TEMP + MACH_FPU_REGS_OFFSET + 4*30],%f30
  426. dontRestoreFPU:
  427.  
  428.     /* restore global registers of new process */
  429.     MACH_RESTORE_GLOBAL_STATE()
  430.  
  431.     /*
  432.      * Restore the local and in registers for this process.  (We need
  433.      * at least the psr in %CUR_PSR_REG and the fp and return pc.)
  434.      * To do this we set the wim to this window and do a save and restore.
  435.      * That way the registers are automatically saved from the stack.
  436.      * We could instead save all these explicitly in the state structure
  437.      * and not do a save and restore, but that wouldn't save that many
  438.      * loads and it also would be different than how we save and restore
  439.      * with the debugger.  It's nice to have them the same.
  440.      */
  441.     MACH_SET_WIM_TO_CWP()
  442.     save
  443.     restore
  444.     /* restore user stack pointer if a user process? */
  445.  
  446.     /*
  447.      * Restore status register in such a way that it doesn't make
  448.      * us change windows.
  449.      */
  450.     MACH_RESTORE_PSR()
  451.     ret
  452.     restore
  453.  
  454. /*
  455.  *---------------------------------------------------------------------
  456.  *
  457.  * MachRunUserProc -
  458.  *
  459.  *    void    MachRunUserProc()
  460.  *
  461.  *    Make the first user process start off by returning it from a kernel
  462.  *    trap.
  463.  *    Interrupts must be disabled coming into this.
  464.  *
  465.  *    MachRunUserProc();
  466.  *
  467.  * Results:
  468.  *    Restore registers and return to user space.
  469.  *
  470.  * Side effects:
  471.  *    Registers restored.
  472.  *
  473.  *---------------------------------------------------------------------
  474.  */
  475. .globl    _MachRunUserProc
  476. _MachRunUserProc:
  477.     /*
  478.      * Get values to restore registers to from the state structure.
  479.      * We set up %VOL_TEMP2 to point to trapRegs structure and restore
  480.      * from there.
  481.      */
  482.     MACH_GET_CUR_STATE_PTR(%VOL_TEMP1, %VOL_TEMP2)    /* into %VOL_TEMP1 */
  483.     sethi    %hi(_machCurStatePtr), %VOL_TEMP2
  484.     st    %VOL_TEMP1, [%VOL_TEMP2 + %lo(_machCurStatePtr)]
  485.     add    %VOL_TEMP1, MACH_TRAP_REGS_OFFSET, %VOL_TEMP1
  486.     ld    [%VOL_TEMP1], %VOL_TEMP2    /* machStatePtr->trapRegs */
  487.     mov    %VOL_TEMP2, %sp            /* set sp to trapRegs */
  488.     /*
  489.      * Restore %fp.  This will be the user's %sp when we return from
  490.      * the trap window.
  491.      */
  492.     add    %VOL_TEMP2, MACH_FP_OFFSET, %VOL_TEMP1
  493.     ld    [%VOL_TEMP1], %fp        /* set %fp - user sp */
  494.     andcc    %fp, 0x7, %g0
  495.     be    UserStackOkay
  496.     nop
  497.     /*
  498.      * User stack wasn't aligned.  It should have been when it got here!
  499.      */
  500.     set    _MachRunUserDeathString, %o0
  501.     call    _printf, 1
  502.     nop
  503.     set    PROC_TERM_DESTROYED, %o0
  504.     set    PROC_BAD_STACK, %o1
  505.     clr    %o2
  506.     set    _Proc_ExitInt, %VOL_TEMP1
  507.     call    %VOL_TEMP1, 3
  508.     nop
  509. UserStackOkay:
  510.     /*
  511.      * Set return from trap pc and next pc.
  512.      */
  513.     add    %VOL_TEMP2, MACH_TRAP_PC_OFFSET, %VOL_TEMP1
  514.     ld    [%VOL_TEMP1], %CUR_PC_REG
  515.     add    %VOL_TEMP1, 4, %VOL_TEMP1
  516.     ld    [%VOL_TEMP1], %NEXT_PC_REG
  517.     add    %VOL_TEMP1, 4, %VOL_TEMP1
  518.     ld    [%VOL_TEMP1], %CUR_TBR_REG
  519.  
  520.     /*
  521.      * Put a return value into the return value register.
  522.      */
  523.     add    %VOL_TEMP2, MACH_ARG0_OFFSET, %VOL_TEMP1
  524.     ld    [%VOL_TEMP1], %i0
  525.     /*
  526.      * Restore the other in registers, which were trapper's out regs.
  527.      * We've already restored fp = i6, so skip it.
  528.      */
  529.     add    %VOL_TEMP1, 4, %VOL_TEMP1
  530.     ld    [%VOL_TEMP1], %i1
  531.     add    %VOL_TEMP1, 4, %VOL_TEMP1
  532.     ld    [%VOL_TEMP1], %i2
  533.     add    %VOL_TEMP1, 4, %VOL_TEMP1
  534.     ld    [%VOL_TEMP1], %i3
  535.     add    %VOL_TEMP1, 4, %VOL_TEMP1
  536.     ld    [%VOL_TEMP1], %i4
  537.     add    %VOL_TEMP1, 4, %VOL_TEMP1
  538.     ld    [%VOL_TEMP1], %i5
  539.  
  540.     add    %VOL_TEMP1, 8, %VOL_TEMP1
  541.     ld    [%VOL_TEMP1], %i7
  542.     /*
  543.      * Get new psr value.
  544.      */
  545.     add    %VOL_TEMP2, MACH_PSR_OFFSET, %VOL_TEMP1
  546.     ld    [%VOL_TEMP1], %CUR_PSR_REG
  547.  
  548.     /*
  549.      * Now go through regular return from trap code.
  550.      * We must make sure that the window we will return to from the trap
  551.      * is invalid when we get into MachReturnFromTrap so that it will
  552.      * be restored from the user stack.  Otherwise the in registers (such
  553.      * as frame pointer) in that window we return to will be bad and
  554.      * won't be restored correctly.
  555.      */
  556.     MACH_SET_WIM_TO_CWP();
  557.     MACH_RETREAT_WIM(%VOL_TEMP1, %VOL_TEMP2);
  558.  
  559.     set    _MachReturnFromTrap, %VOL_TEMP1
  560.     jmp    %VOL_TEMP1
  561.     nop
  562.  
  563. /*
  564.  *---------------------------------------------------------------------
  565.  *
  566.  * MachGetCurrentSp -
  567.  *
  568.  *    Address    MachGetCurrentSp()
  569.  *
  570.  *    Return the value of the current stack pointer.
  571.  *
  572.  * Results:
  573.  *    The current stack pointer.
  574.  *
  575.  * Side effects:
  576.  *    None.
  577.  *
  578.  *---------------------------------------------------------------------
  579.  */
  580. .globl    _MachGetCurrentSp
  581. _MachGetCurrentSp:
  582.     mov    %sp, %o0
  583.     retl
  584.     nop
  585.  
  586.  
  587. /*
  588.  *---------------------------------------------------------------------
  589.  *
  590.  * MachHandleSignal -
  591.  *
  592.  *    void MachHandleSignal()
  593.  *
  594.  *    Setup the necessary stack to handle a signal.  Interrupts are off when
  595.  *    we enter.  They must be off so we don't overwrite the signal stuff
  596.  *    in the process state with more signal stuff.
  597.  *
  598.  * Results:
  599.  *    We return via a rett to user mode to the pc of the signal handler.
  600.  *
  601.  * Side effects:
  602.  *    Depends on signal handler, etc.
  603.  *
  604.  *---------------------------------------------------------------------
  605.  */
  606. .globl    _MachHandleSignal
  607. _MachHandleSignal:
  608.     /*
  609.      * Save window to stack so that user trap values will be saved
  610.      * to kernel stack so that when we copy them to the user stack, we'll
  611.      * get the correct values.
  612.      */
  613.     MACH_SAVE_WINDOW_TO_STACK()
  614.  
  615.     /* Get new user stack pointer value into %SAFE_TEMP */
  616.     sethi    %hi(_machSignalStackSizeOnStack), %VOL_TEMP1
  617.                             /* size MachSignalStack */
  618.     ld    [%VOL_TEMP1 + %lo(_machSignalStackSizeOnStack)], %VOL_TEMP1
  619.     sub    %fp, %VOL_TEMP1, %SAFE_TEMP        /* new sp in safetemp */
  620.  
  621.     /* Copy out sig stack from state structure to user stack */
  622.     sethi    %hi(_machSigStackOffsetOnStack), %VOL_TEMP1
  623.                             /* offset Sig_Stack */
  624.     ld    [%VOL_TEMP1 + %lo(_machSigStackOffsetOnStack)], %VOL_TEMP1
  625.     add    %SAFE_TEMP, %VOL_TEMP1, %o2    /* dest addr of Sig_Stack */
  626.     sethi    %hi(_machSigStackSize), %o0
  627.     ld    [%o0 + %lo(_machSigStackSize)], %o0    /* size of Sig_Stack */
  628.     MACH_GET_CUR_STATE_PTR(%VOL_TEMP1, %VOL_TEMP2)    /* into %VOL_TEMP1 */
  629.     sethi    %hi(_machSigStackOffsetInMach), %VOL_TEMP2
  630.     ld    [%VOL_TEMP2 + %lo(_machSigStackOffsetInMach)], %VOL_TEMP2
  631.     add    %VOL_TEMP1, %VOL_TEMP2, %o1    /* src addr of sig stack */
  632.     QUICK_ENABLE_INTR(%VOL_TEMP1)
  633.     call    _Vm_CopyOut, 3                /* copy Sig_Stack */
  634.     nop
  635.     QUICK_DISABLE_INTR(%VOL_TEMP1)
  636.     be    CopiedOutSigStack
  637.     nop
  638. CopyOutForSigFailed:
  639.     /*
  640.      * Copying to user stack failed.  We have no choice but to kill the
  641.      * thing.  This causes us to exit this routine and process.
  642.      */
  643.     set    _MachHandleSignalDeathString, %o0
  644.     call    _printf, 1
  645.     nop
  646.     set    PROC_TERM_DESTROYED, %o0
  647.     set    PROC_BAD_STACK, %o1
  648.     clr    %o2
  649.     call    _Proc_ExitInt, 3
  650.     nop
  651.  
  652. CopiedOutSigStack:
  653.     /* Copy out sig context from state structure to user stack */
  654.     /* put addr of mach state structure in %VOL_TEMP1 again */
  655.     MACH_GET_CUR_STATE_PTR(%VOL_TEMP1, %VOL_TEMP2)    /* into %VOL_TEMP1 */
  656.     sethi    %hi(_machSigContextOffsetOnStack), %VOL_TEMP2
  657.                             /* offset Sig_Context */
  658.     ld    [%VOL_TEMP2 + %lo(_machSigContextOffsetOnStack)], %VOL_TEMP2
  659.     add    %SAFE_TEMP, %VOL_TEMP2, %o2    /* dest addr of Sig_Context */
  660.     sethi    %hi(_machSigContextSize), %o0
  661.                         /* size of Sig_Context */
  662.     ld    [%o0 + %lo(_machSigContextSize)], %o0
  663.     sethi    %hi(_machSigContextOffsetInMach), %VOL_TEMP2
  664.                         /* offset Sig_Context */
  665.     ld    [%VOL_TEMP2 + %lo(_machSigContextOffsetInMach)], %VOL_TEMP2
  666.     add    %VOL_TEMP1, %VOL_TEMP2, %o1    /* src addr of sig context */
  667.     QUICK_ENABLE_INTR(%VOL_TEMP1)
  668.     call    _Vm_CopyOut, 3                /* copy Sig_Context */
  669.     nop
  670.     QUICK_DISABLE_INTR(%VOL_TEMP1)
  671.     bne    CopyOutForSigFailed
  672.     nop
  673.  
  674.     /* Copy out user trap state from state structure to user stack */
  675.     /* put addr of mach state structure in %VOL_TEMP1 again */
  676.     MACH_GET_CUR_STATE_PTR(%VOL_TEMP1, %VOL_TEMP2)    /* into %VOL_TEMP1 */
  677.     sethi    %hi(_machSigUserStateOffsetOnStack), %VOL_TEMP2
  678.     ld    [%VOL_TEMP2 + %lo(_machSigUserStateOffsetOnStack)], %VOL_TEMP2
  679.     add    %SAFE_TEMP, %VOL_TEMP2, %o2    /* dest addr of user state */
  680.     set    MACH_SAVED_STATE_FRAME, %o0    /* size of copy */
  681.     add    %VOL_TEMP1, MACH_TRAP_REGS_OFFSET, %VOL_TEMP1
  682.     ld    [%VOL_TEMP1], %o1        /* address of trap regs */
  683.     QUICK_ENABLE_INTR(%VOL_TEMP1)
  684.     call    _Vm_CopyOut, 3
  685.     nop
  686.     QUICK_DISABLE_INTR(%VOL_TEMP1)
  687.     bne    CopyOutForSigFailed
  688.     nop
  689.  
  690.     /*
  691.      * Get address of trapInst field in machContext field of sig context
  692.      * and put it in ret addr of next window so when we return from handler
  693.      * in next window, we'll return to the trap instruction.
  694.      */
  695.     sethi    %hi(_machSigTrapInstOffsetOnStack), %VOL_TEMP2
  696.                         /* offset to trap instr */
  697.     ld    [%VOL_TEMP2 + %lo(_machSigTrapInstOffsetOnStack)], %VOL_TEMP2
  698.     add    %SAFE_TEMP, %VOL_TEMP2, %RETURN_ADDR_REG    /* addr */
  699.     /* ret from proc instr jumps to (ret addr + 8), so subtract 8 here */
  700.     sub    %RETURN_ADDR_REG, 0x8, %RETURN_ADDR_REG
  701.  
  702.     /*
  703.      * Set return from trap pc and next pc in the next window to the
  704.      * address of the handler so that when we do a rett back to this
  705.      * window from the next window, we'll start executing at the signal
  706.      * handler.  This requires a global register to get
  707.      * it across the window boundary, so we must do this before restoring
  708.      * our global registers.  This should be done after the Vm_CopyOut's
  709.      * so that there's no overwriting our confusion with the registers
  710.      * in the next window.
  711.      */
  712.     sethi    %hi(_machSigPCOffsetOnStack), %VOL_TEMP1
  713.                             /* offset to pc field */
  714.     ld    [%VOL_TEMP1 + %lo(_machSigPCOffsetOnStack)], %VOL_TEMP1
  715.     add    %SAFE_TEMP, %VOL_TEMP1, %VOL_TEMP1    /* addr of sig pc */
  716.     ld    [%VOL_TEMP1], %g3
  717.  
  718.     save
  719.     mov    %g3, %CUR_PC_REG        /* trap pc addr into rett pc */
  720.     add    %g3, 0x4, %NEXT_PC_REG
  721.     restore
  722.  
  723.     /*
  724.      * restore global regs for user after calling Vm_CopyOut and after
  725.      * using %g3 (above) and before messing up our kernel stack pointer.
  726.      */
  727.     MACH_RESTORE_GLOBAL_STATE()
  728.  
  729.     /*
  730.      * Set up our out registers to be correct arguments to sig handler,
  731.      * since this is the window it will start off in, but the C code will
  732.      * do a save into the next window so our out's will be the handler's
  733.      * in regs.
  734.      *
  735.      *    Handler(sigNum, sigCode, contextPtr, sigAddr)
  736.      */
  737.     MACH_GET_CUR_STATE_PTR(%VOL_TEMP1, %VOL_TEMP2)    /* into %VOL_TEMP1 */
  738.     sethi    %hi(_machSigStackOffsetInMach), %VOL_TEMP2
  739.                         /* offset to sig stack */
  740.     ld    [%VOL_TEMP2 + %lo(_machSigStackOffsetInMach)], %VOL_TEMP2
  741.     add    %VOL_TEMP1, %VOL_TEMP2, %VOL_TEMP2    /* addr of sig stack */
  742.     sethi    %hi(_machSigNumOffsetInSig), %o0
  743.                         /* offset to sigNum */
  744.     ld    [%o0 + %lo(_machSigNumOffsetInSig)], %o0
  745.     add    %o0, %VOL_TEMP2, %o0        /* addr of sig num */
  746.     ld    [%o0], %o0            /* sig num == arg 1 */
  747.     sethi    %hi(_machSigCodeOffsetInSig), %o1
  748.                         /* offset to sigCode */
  749.     ld    [%o1 + %lo(_machSigCodeOffsetInSig)], %o1
  750.     add    %o1, %VOL_TEMP2, %o1        /* addr of sig code */
  751.     ld    [%o1], %o1            /* sig code == arg2 */
  752.     /* Stack address of Sig_Context is third arg */
  753.     sethi    %hi(_machSigContextOffsetOnStack), %VOL_TEMP2
  754.                             /* offset Sig_Context */
  755.     ld    [%VOL_TEMP2 + %lo(_machSigContextOffsetOnStack)], %VOL_TEMP2
  756.     add    %SAFE_TEMP, %VOL_TEMP2, %o2    /* stack addr context = arg3  */
  757.     sethi    %hi(_machSigStackOffsetInMach), %VOL_TEMP2
  758.                         /* offset to sig stack */
  759.     ld    [%VOL_TEMP2 + %lo(_machSigStackOffsetInMach)], %VOL_TEMP2
  760.     add    %VOL_TEMP1, %VOL_TEMP2, %VOL_TEMP2    /* addr of sig stack */
  761.     sethi    %hi(_machSigAddrOffsetInSig), %o3
  762.                         /* offset to sigAddr */
  763.     ld    [%o3 + %lo(_machSigAddrOffsetInSig)], %o3
  764.     add    %o3, %VOL_TEMP2, %o3        /* addr of sig addr */
  765.     ld    [%o3], %o3            /* sig addr == arg 4 */
  766.  
  767.     /*
  768.      * NOTE: the sigStack.sigContextPtr field has not been filled in.
  769.      * Will that matter?
  770.      */
  771.  
  772.     /* set stack pointer in this window to new user stack pointer */
  773.     mov    %SAFE_TEMP, %sp
  774.  
  775.     /*
  776.      * Move the user psr to restore to next window, since we'll have
  777.      * to restore it from there since it disables traps and we must still
  778.      * have traps enabled when executing the save instruction, in case
  779.      * of window overflow.
  780.      */
  781.     mov    %CUR_PSR_REG, %o4
  782.  
  783.     /*
  784.      * Move to window to do rett from.  We must do this while traps are
  785.      * still enabled, in case we get overflow.
  786.      */
  787.     save
  788.  
  789.     /*
  790.      * Set up psr for return to user mode.  It must be the user mode
  791.      * psr with traps disabled.
  792.      */
  793.     mov    %i4, %CUR_PSR_REG        /* so restore psr will work */
  794.     MACH_RESTORE_PSR()
  795.  
  796.     jmp    %CUR_PC_REG
  797.     rett    %NEXT_PC_REG
  798.  
  799. /*
  800.  *---------------------------------------------------------------------
  801.  *
  802.  * MachReturnFromSignal -
  803.  *
  804.  *    void MachReturnFromSignal()
  805.  *
  806.  *    The routine executed after a return from signal trap.  This must
  807.  *    restore state from the user stack so we can return to user mode
  808.  *    via the regular return from trap method.
  809.  *
  810.  *    Interrupts must be off when we're called.
  811.  *
  812.  * Results:
  813.  *    We execute the return-from-trap code, so it depends what happens there.
  814.  *
  815.  * Side effects:
  816.  *    Depends.
  817.  *
  818.  *---------------------------------------------------------------------
  819.  */
  820. .globl    _MachReturnFromSignal
  821. _MachReturnFromSignal:
  822.     /*
  823.      * We've trapped into this window so our %fp is the user's sp that
  824.      * we set up before handling the signal.  We must copy stuff back off
  825.      * the user's stack to the trap regs to restore state.  But we're one
  826.      * window away from where we want to be, so we have to back up also.
  827.      */
  828.     /* get our kernel stack pointer into global regs (which get restored
  829.      * in MachReturnFromTrap) so we can keep it across windows.
  830.      */
  831.     mov    %sp, %g3
  832.     restore        /* no underflow since we just came from here */
  833.     /*
  834.      * I could at this point just move %sp to %SAFE_TEMP if I really
  835.      * trusted that %fp - sizeof (MachSignalStack) really equals %sp which
  836.      * was user sp we set up before calling signal handler, but I
  837.      * check this for now.
  838.      */
  839.     sethi    %hi(_machSignalStackSizeOnStack), %VOL_TEMP1
  840.                         /* size MachSignalStack */
  841.     ld    [%VOL_TEMP1 + %lo(_machSignalStackSizeOnStack)], %VOL_TEMP1
  842.     sub    %fp, %VOL_TEMP1, %SAFE_TEMP    /* sig user sp in safetemp */
  843.     cmp    %SAFE_TEMP, %sp
  844.     bne    CopyInForSigFailed
  845.     nop
  846.  
  847.     mov    %g3, %sp            /* kernel sp now here too */
  848.  
  849.     /* Copy in sig stack from user stack to mach state structure */
  850.     sethi    %hi(_machSigStackOffsetOnStack), %VOL_TEMP1
  851.                         /* offset of Sig_Stack */
  852.     ld    [%VOL_TEMP1 + %lo(_machSigStackOffsetOnStack)], %VOL_TEMP1
  853.     add    %SAFE_TEMP, %VOL_TEMP1, %o1    /* src addr of Sig_Stack */
  854.     sethi    %hi(_machSigStackSize), %o0
  855.                         /* size of Sig_Stack */
  856.     ld    [%o0 + %lo(_machSigStackSize)], %o0
  857.     MACH_GET_CUR_STATE_PTR(%VOL_TEMP1, %VOL_TEMP2)    /* into %VOL_TEMP1 */
  858.     sethi    %hi(_machSigStackOffsetInMach), %VOL_TEMP2
  859.     ld    [%VOL_TEMP2 + %lo(_machSigStackOffsetInMach)], %VOL_TEMP2
  860.     add    %VOL_TEMP1, %VOL_TEMP2, %o2    /* dest addr of sig stack */
  861.     QUICK_ENABLE_INTR(%VOL_TEMP1)
  862.     call    _Vm_CopyIn, 3            /* copy Sig_Stack */
  863.     nop
  864.     QUICK_DISABLE_INTR(%VOL_TEMP1)
  865.     be    CopiedInSigStack
  866.     nop
  867. CopyInForSigFailed:
  868.      /* Copy failed from user space - kill the process */
  869.     set    _MachReturnFromSignalDeathString, %o0
  870.     call    _printf, 1
  871.     nop
  872.     set    PROC_TERM_DESTROYED, %o0
  873.     set    PROC_BAD_STACK, %o1
  874.     clr    %o2
  875.     call    _Proc_ExitInt, 3
  876.     nop
  877.  
  878. CopiedInSigStack:
  879.     /* Copy in sig context from user stack to state structure */
  880.     /* put addr of mach state structure in %VOL_TEMP1 again */
  881.     MACH_GET_CUR_STATE_PTR(%VOL_TEMP1, %VOL_TEMP2)    /* into %VOL_TEMP1 */
  882.     sethi    %hi(_machSigContextOffsetOnStack), %VOL_TEMP2
  883.                         /* offset Sig_Context */
  884.     ld    [%VOL_TEMP2 + %lo(_machSigContextOffsetOnStack)], %VOL_TEMP2
  885.     add    %SAFE_TEMP, %VOL_TEMP2, %o1    /* src addr of Sig_Context */
  886.     sethi    %hi(_machSigContextSize), %o0
  887.                         /* size of Sig_Context */
  888.     ld    [%o0 + %lo(_machSigContextSize)], %o0
  889.     sethi    %hi(_machSigContextOffsetInMach), %VOL_TEMP2
  890.                         /* offset of Sig_Context */
  891.     ld    [%VOL_TEMP2 + %lo(_machSigContextOffsetInMach)], %VOL_TEMP2
  892.     add    %VOL_TEMP1, %VOL_TEMP2, %o2    /* dest addr of sig context */
  893.     QUICK_ENABLE_INTR(%VOL_TEMP1)
  894.     call    _Vm_CopyIn, 3            /* copy Sig_Context */
  895.     nop
  896.     QUICK_DISABLE_INTR(%VOL_TEMP1)
  897.     bne    CopyInForSigFailed
  898.     nop
  899.  
  900.     /*
  901.      * Call a routine that calls Sig_Return with appropriate stuff.
  902.      * This occurs after copying in the Sig stuff, above, because Sig_Return
  903.      * needs the Sig stuff.
  904.      */
  905.     call    _MachCallSigReturn
  906.     nop
  907.  
  908.     /* Copy in user trap state from user stack to kernel trap regs */
  909.     sethi    %hi(_machSigUserStateOffsetOnStack), %VOL_TEMP2
  910.     ld    [%VOL_TEMP2 + %lo(_machSigUserStateOffsetOnStack)], %VOL_TEMP2
  911.     add    %SAFE_TEMP, %VOL_TEMP2, %o1        /* src addr of copy */
  912.     set    MACH_SAVED_STATE_FRAME, %o0        /* size of copy */
  913.     /* destination of copy is trapRegs, but our sp points to that already */
  914.     /* SHOULD I VERIFY THIS? */
  915.     mov    %sp, %o2                /* dest addr of copy */
  916.     QUICK_ENABLE_INTR(%VOL_TEMP1)
  917.     call    _Vm_CopyIn, 3
  918.     nop
  919.     QUICK_DISABLE_INTR(%VOL_TEMP1)
  920.     bne    CopyInForSigFailed
  921.     nop
  922.  
  923.     /* Restore user trap state */
  924.     mov    %sp, %g3            /* save stack pointer */
  925.     MACH_RESTORE_WINDOW_FROM_STACK()
  926.     /* test if stack pointer is the same */
  927.     cmp    %g3, %sp
  928.     mov    %g3, %sp        /* restore, in case it was bad */
  929.     bne    CopyInForSigFailed
  930.     nop
  931.  
  932.     /* Make sure the psr is okay since we got it from the user */
  933.     set    ~(MACH_PS_BIT), %VOL_TEMP1
  934.     and    %CUR_PSR_REG, %VOL_TEMP1, %CUR_PSR_REG    /* clear ps bit */
  935.     set    MACH_DISABLE_TRAP_BIT, %VOL_TEMP1
  936.     and    %CUR_PSR_REG, %VOL_TEMP1, %CUR_PSR_REG    /* clear trap en. bit */
  937.  
  938.     /*
  939.      * Now go through the regular return from trap code.
  940.      */
  941.     call    _MachReturnFromTrap
  942.     nop
  943.  
  944.  
  945. /*
  946.  *---------------------------------------------------------------------
  947.  *
  948.  * Mach_ReadPsr -
  949.  *
  950.  *    Capture %psr for C routines.
  951.  *
  952.  * Results:
  953.  *    %psr.
  954.  *
  955.  * Side effects:
  956.  *    None.
  957.  *
  958.  *---------------------------------------------------------------------
  959.  */
  960. .globl    _Mach_ReadPsr
  961. _Mach_ReadPsr:
  962.     mov    %psr, %o0
  963.     retl
  964.     nop
  965.  
  966. #ifdef sun4c
  967. .globl    _MachGetSyncErrorReg
  968. _MachGetSyncErrorReg:
  969.     set    VMMACH_SYNC_ERROR_REG, %o0
  970.     lda    [%o0] VMMACH_CONTROL_SPACE, %o0
  971.     retl
  972.     nop
  973.  
  974. .globl    _MachGetASyncErrorReg
  975. _MachGetASyncErrorReg:
  976.     set    VMMACH_ASYNC_ERROR_REG, %o0
  977.     lda    [%o0] VMMACH_CONTROL_SPACE, %o0
  978.     retl
  979.     nop
  980.  
  981. .globl    _MachGetSyncErrorAddrReg
  982. _MachGetSyncErrorAddrReg:
  983.     set    VMMACH_SYNC_ERROR_ADDR_REG, %o0
  984.     lda    [%o0] VMMACH_CONTROL_SPACE, %o0
  985.     retl
  986.     nop
  987.  
  988. .globl    _MachGetASyncErrorAddrReg
  989. _MachGetASyncErrorAddrReg:
  990.     set    VMMACH_ASYNC_ERROR_ADDR_REG, %o0
  991.     lda    [%o0] VMMACH_CONTROL_SPACE, %o0
  992.     retl
  993.     nop
  994.  
  995. .globl    _MachGetSystemEnableReg
  996. _MachGetSystemEnableReg:
  997.     set    VMMACH_SYSTEM_ENABLE_REG, %o0
  998.     lduba    [%o0] VMMACH_CONTROL_SPACE, %o0
  999.     retl
  1000.     nop
  1001. #endif
  1002.  
  1003. /*
  1004.  *---------------------------------------------------------------------
  1005.  *
  1006.  * MachHandleBadArgs -
  1007.  *
  1008.  *    A page fault occured in a copy-in or copy-out from a user-mode process,
  1009.  *    and the page couldn't be paged in.  So we want to return
  1010.  *    SYS_ARG_NOACCESS to the process from its system call.
  1011.  *    This means we must return this value from the routine doing the copying.
  1012.  *
  1013.  * Results:
  1014.  *    SYS_ARG_NOACCESS returned to process as if returned from its system
  1015.  *    call.
  1016.  *
  1017.  * Side effects:
  1018.  *    We cause the routine that was copying args to return SYS_ARG_NO_ACCESS.
  1019.  *
  1020.  *---------------------------------------------------------------------
  1021.  */
  1022. .globl    _MachHandleBadArgs
  1023. _MachHandleBadArgs:
  1024.     restore            /* back to page fault trap window */
  1025.     mov    %CUR_PSR_REG, %i1
  1026.     restore            /* back to copy routine that got trap */
  1027.     /* Copy routine was leaf routine and so return failure in %o0 */
  1028.     set    SYS_ARG_NOACCESS, %o0
  1029.     /* Set interrupts to what they were when trap occured. */
  1030.     SET_INTRS_TO(%o1, %OUT_TEMP1, %OUT_TEMP2)
  1031.     retl            /* return from leaf routine */
  1032.     nop
  1033.  
  1034. /*
  1035.  * Beginning of area where the kernel should be able to handle a bus error
  1036.  * (which includes size errors) while in kernel mode.
  1037.  */
  1038. .globl    _MachProbeStart
  1039. _MachProbeStart:
  1040.  
  1041. /*
  1042.  * ----------------------------------------------------------------------
  1043.  *
  1044.  * Mach_Probe --
  1045.  *
  1046.  *    Read or write a virtual address handling bus errors that may occur.
  1047.  *    This routine is intended to be used to probe for memory-mapped devices.
  1048.  *
  1049.  *    Mach_Probe(byteCount, readAddress, writeAddress)
  1050.  *
  1051.  * Results:
  1052.  *    SUCCESS if the read or write worked and FAILURE otherwise.
  1053.  *
  1054.  * Side effects:
  1055.  *    None.
  1056.  *
  1057.  * ----------------------------------------------------------------------
  1058.  */
  1059. .globl    _Mach_Probe
  1060. _Mach_Probe:
  1061.                 /* %o0 = size in bytes of the read/write to do.
  1062.                  * Must be 1, 2, 4, or 8 bytes. */
  1063.                 /* %o1 = address to read. */
  1064.                 /* %o2 = Location to store the read value. */
  1065.     cmp    %o0, 1
  1066.     bne    Read2Bytes
  1067.     nop
  1068.     ldub    [%o1], %OUT_TEMP1
  1069.     stb    %OUT_TEMP1, [%o2]
  1070.     set    SUCCESS, %RETURN_VAL_REG
  1071.     retl
  1072.     nop
  1073. Read2Bytes:
  1074.     cmp    %o0, 2
  1075.     bne    Read4Bytes
  1076.     nop
  1077.     andcc    %o1, 0x1, %g0
  1078.     bne    BadRead
  1079.     nop
  1080.     andcc    %o2, 0x1, %g0
  1081.     bne    BadRead
  1082.     nop
  1083.     lduh    [%o1], %OUT_TEMP1
  1084.     sth    %OUT_TEMP1, [%o2]
  1085.     set    SUCCESS, %RETURN_VAL_REG
  1086.     retl
  1087.     nop
  1088. Read4Bytes:
  1089.     cmp    %o0, 4
  1090.     bne    Read8Bytes
  1091.     nop
  1092.     andcc    %o1, 0x3, %g0
  1093.     bne    BadRead
  1094.     nop
  1095.     andcc    %o2, 0x3, %g0
  1096.     bne    BadRead
  1097.     nop
  1098.     ld    [%o1], %OUT_TEMP1
  1099.     st    %OUT_TEMP1, [%o2]
  1100.     set    SUCCESS, %RETURN_VAL_REG
  1101.     retl
  1102.     nop
  1103. Read8Bytes:
  1104.     cmp    %o0, 8
  1105.     bne    BadRead
  1106.     nop
  1107.     andcc    %o1, 0x7, %g0
  1108.     bne    BadRead
  1109.     nop
  1110.     andcc    %o2, 0x7, %g0
  1111.     bne    BadRead
  1112.     nop
  1113.     ldd    [%o1], %OUT_TEMP1
  1114.     std    %OUT_TEMP1, [%o2]
  1115.     set    SUCCESS, %RETURN_VAL_REG
  1116.     retl
  1117.     nop
  1118. BadRead:
  1119.     set    FAILURE, %RETURN_VAL_REG
  1120.     retl
  1121.     nop
  1122.  
  1123. /*
  1124.  * End of the area where the kernel should be able to handle a bus error
  1125.  * while in kernel mode.
  1126.  */
  1127. .globl    _MachProbeEnd
  1128. _MachProbeEnd:
  1129.  
  1130. /*
  1131.  *---------------------------------------------------------------------
  1132.  *
  1133.  * MachHandleBadProbe -
  1134.  *
  1135.  *    A page fault occured during a probe operation, which means
  1136.  *    the page couldn't be paged in or there was a size error.  So we want to
  1137.  *    return FAILURE to the caller of the probe operation.  This means we must
  1138.  *    return this value from the routine doing the probe.
  1139.  *
  1140.  * Results:
  1141.  *    FAILURE returned to caller of probe operation.
  1142.  *
  1143.  * Side effects:
  1144.  *    We cause the routine that was doing the probe to return FAILURE.
  1145.  *
  1146.  *---------------------------------------------------------------------
  1147.  */
  1148. .globl    _MachHandleBadProbe
  1149. _MachHandleBadProbe:
  1150.     restore        /* back to page fault trap window */
  1151.     mov    %CUR_PSR_REG, %i1    /* get trap psr */
  1152.     restore        /* back to probe routine window */
  1153.     /* Mach_Probe is a leaf routine - return stuff in %o0 */
  1154.     set    FAILURE, %o0    /* return FAILURE */
  1155.     /* Set interrupts to what they were when trap occured. */
  1156.     SET_INTRS_TO(%o1, %OUT_TEMP1, %OUT_TEMP2)
  1157.     retl        /* return from leaf routine */
  1158.     nop
  1159.  
  1160. /*
  1161.  *---------------------------------------------------------------------
  1162.  *
  1163.  * MachHandleBadQuickCopy -
  1164.  *
  1165.  *    A page fault occured during a quick copy operation, which isn't
  1166.  *    allowed.  So we want to return FAILURE to the caller of the copy
  1167.  *    operation.  This means we must return this value from the routine
  1168.  *    doing the copy.
  1169.  *
  1170.  * Results:
  1171.  *    FAILURE returned to caller of copy operation.
  1172.  *
  1173.  * Side effects:
  1174.  *    We cause the routine that was doing the copy to return FAILURE.
  1175.  *
  1176.  *---------------------------------------------------------------------
  1177.  */
  1178. .globl    _MachHandleBadQuickCopy
  1179. _MachHandleBadQuickCopy:
  1180.     restore        /* back to page fault trap window */
  1181.     mov    %CUR_PSR_REG, %i1    /* get trap psr */
  1182.     restore        /* back to copy routine window */
  1183.     /* VmMachQuickNDirtyCopy is NOT a leaf routine - return stuff in %i0 */
  1184.     set    FAILURE, %i0    /* return FAILURE */
  1185.     /* Set interrupts to what they were when trap occured. */
  1186.     SET_INTRS_TO(%o1, %OUT_TEMP1, %OUT_TEMP2)
  1187.     ret        /* return from non-leaf routine */
  1188.     restore
  1189. /*
  1190.  *---------------------------------------------------------------------
  1191.  *
  1192.  * _MachFPULoadState -
  1193.  *
  1194.  *    Load the current state into the FPU.
  1195.  *
  1196.  *    void MachFPULoadState(regStatePtr)
  1197.  *          Mach_RegState *regStatePtr;
  1198.  * Results:
  1199.  *    None
  1200.  *
  1201.  * Side effects:
  1202.  *    FPU registers changed.
  1203.  *
  1204.  *---------------------------------------------------------------------
  1205.  */
  1206. .globl    _MachFPULoadState
  1207. _MachFPULoadState:
  1208.     /*
  1209.      * Insure that the FPU is enabled.
  1210.      */
  1211.     mov    %psr, %o1
  1212.     set    MACH_ENABLE_FPP, %o2
  1213.     or    %o2,%o1,%o2
  1214.     mov    %o2,%psr
  1215.     nop
  1216.     nop
  1217.     nop
  1218.     ld    [%o0 + MACH_FPU_FSR_OFFSET], %fsr
  1219.     ldd    [%o0 + MACH_FPU_REGS_OFFSET+4*0],%f0
  1220.     ldd    [%o0 + MACH_FPU_REGS_OFFSET+4*2],%f2
  1221.     ldd    [%o0 + MACH_FPU_REGS_OFFSET+4*4],%f4
  1222.     ldd    [%o0 + MACH_FPU_REGS_OFFSET+4*6],%f6
  1223.     ldd    [%o0 + MACH_FPU_REGS_OFFSET+4*8],%f8
  1224.     ldd    [%o0 + MACH_FPU_REGS_OFFSET+4*10],%f10
  1225.     ldd    [%o0 + MACH_FPU_REGS_OFFSET+4*12],%f12
  1226.     ldd    [%o0 + MACH_FPU_REGS_OFFSET+4*14],%f14
  1227.     ldd    [%o0 + MACH_FPU_REGS_OFFSET+4*16],%f16
  1228.     ldd    [%o0 + MACH_FPU_REGS_OFFSET+4*18],%f18
  1229.     ldd    [%o0 + MACH_FPU_REGS_OFFSET+4*20],%f20
  1230.     ldd    [%o0 + MACH_FPU_REGS_OFFSET+4*22],%f22
  1231.     ldd    [%o0 + MACH_FPU_REGS_OFFSET+4*24],%f24
  1232.     ldd    [%o0 + MACH_FPU_REGS_OFFSET+4*26],%f26
  1233.     ldd    [%o0 + MACH_FPU_REGS_OFFSET+4*28],%f28
  1234.     ldd    [%o0 + MACH_FPU_REGS_OFFSET+4*30],%f30
  1235.     retl
  1236.     mov    %o1,%psr
  1237. /*
  1238.  *---------------------------------------------------------------------
  1239.  *
  1240.  * MachFPUDumpState -
  1241.  *
  1242.  *    Save the FPU state of a process into the Mach_RegState structure.
  1243.  *
  1244.  *    void MachFPUDumpState(regStatePtr)
  1245.  *        Mach_RegState *regStatePtr;
  1246.  *
  1247.  * Results:
  1248.  *    None
  1249.  *
  1250.  * Side effects:
  1251.  *    Pending exception state cleared from FPU.
  1252.  *
  1253.  *---------------------------------------------------------------------
  1254.  */
  1255. .globl    _MachFPUDumpState
  1256. _MachFPUDumpState:
  1257.     /*
  1258.      * Insure that the FPU is enabled.
  1259.      */
  1260.     mov    %psr, %o1
  1261.     set    MACH_ENABLE_FPP, %o2
  1262.     or    %o2,%o1,%o2
  1263.     mov    %o2,%psr
  1264.     /*
  1265.      * Next three instructions should not be FPU instructions.
  1266.      */
  1267.     set     MACH_FSR_QUEUE_NOT_EMPTY, %o3
  1268.     add    %o0, MACH_FPU_QUEUE_OFFSET, %o4
  1269.     mov    0, %o5
  1270.  
  1271.     /*
  1272.      * We have to do the same trick here as in Mach_ContextSwitch,
  1273.      * flagging the instruction that waits for the FPU to finish
  1274.      * and checking for exceptions.  We have a different label this
  1275.      * time, of course.  The trap handler knows that if the trap
  1276.      * occurred at this label then we were already dumping the state
  1277.      * and it shouldn't call us recursively.
  1278.      * Note that the fsr is read again in the loop, and the purpose
  1279.      * of this extra read is to have a separate label for the first
  1280.      * read -- traps on subsequent reads of fsr would be an error.
  1281.      */
  1282. .global _machFPUDumpSyncInst
  1283. _machFPUDumpSyncInst:
  1284.     st    %fsr, [%o0 + MACH_FPU_FSR_OFFSET]
  1285.         /*
  1286.      * The following symbol is include to make the following code
  1287.      * be attributed to the routine MachFPUDumpState2 and not
  1288.      * _machFPUDumpSyncInst.
  1289.      */
  1290. .globl    MachFPUDumpState2
  1291. MachFPUDumpState2:
  1292.     /*
  1293.      * While MACH_FSR_QUEUE_NOT_EMPTY set in the FSR, save
  1294.      * the entry in the %fq register.
  1295.      */
  1296. clearQueueLoop:
  1297.     st    %fsr, [%o0 + MACH_FPU_FSR_OFFSET]
  1298.     ld      [%o0 + MACH_FPU_FSR_OFFSET], %o2
  1299.     andcc    %o2,%o3,%g0
  1300.     be    queueEmpty
  1301.     nop
  1302.     std    %fq, [%o4+%o5]
  1303.     ba    clearQueueLoop
  1304.     add    %o5,8,%o5
  1305. queueEmpty:
  1306.     /*
  1307.      * Compute numQueueEntries.
  1308.      */
  1309.     srl    %o5,3,%o5
  1310.     st    %o5, [%o0 + MACH_FPU_QUEUE_COUNT]
  1311.     /*
  1312.      * Save registers two at a time.
  1313.      */
  1314.     std    %f0, [%o0 + MACH_FPU_REGS_OFFSET+4*0]
  1315.     std    %f2, [%o0 + MACH_FPU_REGS_OFFSET+4*2]
  1316.     std    %f4, [%o0 + MACH_FPU_REGS_OFFSET+4*4]
  1317.     std    %f6, [%o0 + MACH_FPU_REGS_OFFSET+4*6]
  1318.     std    %f8, [%o0 + MACH_FPU_REGS_OFFSET+4*8]
  1319.     std    %f10, [%o0 + MACH_FPU_REGS_OFFSET+4*10]
  1320.     std    %f12, [%o0 + MACH_FPU_REGS_OFFSET+4*12]
  1321.     std    %f14, [%o0 + MACH_FPU_REGS_OFFSET+4*14]
  1322.     std    %f16, [%o0 + MACH_FPU_REGS_OFFSET+4*16]
  1323.     std    %f18, [%o0 + MACH_FPU_REGS_OFFSET+4*18]
  1324.     std    %f20, [%o0 + MACH_FPU_REGS_OFFSET+4*20]
  1325.     std    %f22, [%o0 + MACH_FPU_REGS_OFFSET+4*22]
  1326.     std    %f24, [%o0 + MACH_FPU_REGS_OFFSET+4*24]
  1327.     std    %f26, [%o0 + MACH_FPU_REGS_OFFSET+4*26]
  1328.     std    %f28, [%o0 + MACH_FPU_REGS_OFFSET+4*28]
  1329.     std    %f30, [%o0 + MACH_FPU_REGS_OFFSET+4*30]
  1330.     /*
  1331.      * Restore the FPU to previous state and return.
  1332.      */
  1333.     retl
  1334.     mov    %o1,%psr
  1335.  
  1336. /*
  1337.  * ----------------------------------------------------------------------
  1338.  *
  1339.  * Mach_Return2(val)  --
  1340.  *
  1341.  *    Set the second return value.
  1342.  *
  1343.  * Results:
  1344.  *    None.
  1345.  *
  1346.  * Side effects:
  1347.  *    i1 <- val.
  1348.  *
  1349.  * ----------------------------------------------------------------------
  1350.  */
  1351. .globl    _Mach_Return2
  1352. _Mach_Return2:
  1353.     retl
  1354.     mov    %o0, %i1
  1355.